<?php

declare(strict_types=1);

namespace cosy\framework\traits;

use cosy\framework\model\CosyModel;
use think\db\exception\DbException;
use think\Paginator;
use think\model\Collection;
use think\db\BaseQuery as Query;

/**
 * ClassName MapperTrait
 * Description TODO
 * Author BTC
 * Date 2023/10/31 14:16
 **/
trait MapperTrait
{
    /**
     * 获取数据列表
     * @param array $params
     * @return Collection
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList(array $params = []): Collection
    {
        $query = $this->getQuery(__FUNCTION__, $params);
        if (!isset($query->getOptions()['order'])) { // 如果未设置排序时, 默认按主键倒序
            $query->order($this->model->getPk(), 'desc');
        }

        return $query->select();
    }

    protected function getQuery(string $method, array $params = []): Query
    {
        $function = $method . 'Handle';
        return method_exists($this, $function) ? $this->$function($this->model::query(), $params) : $this->model::query();
    }

    /**
     * 获取列表数据（带分页）
     * @param array $params
     * @return Paginator
     * @throws DbException
     */
    public function getPageList(array $params = []): Paginator
    {
        $query = $this->getQuery(__FUNCTION__, $params);
        if (!isset($query->getOptions()['order'])) { // 如果未设置排序时, 默认按主键倒序
            $query->order($this->model->getPk(), 'desc');
        }

        return $query->paginate($data['pageSize'] ?? $this->model::PAGE_SIZE);
    }

    /**
     * 根据主键读取一条数据
     * @param int $id
     * @return CosyModel
     */
    public function read(int $id): CosyModel
    {
        $query = $this->getQuery(__FUNCTION__);

        return $query->findOrEmpty($id);
    }

    /**
     * 按条件读取一行数据
     *
     * @param array $where
     * @return CosyModel
     */
    public function first(array $where): CosyModel
    {
        return $this
            ->model
            ->where($where)
            ->findOrEmpty();
    }

    /**
     * 新增/编辑数据
     *
     * @param array $data
     * @return int
     */
    public function save(array $data): bool
    {
        if (!empty($data['id'])) {
            unset($data['create_time'], $data['update_time']);
            $this->model = $this->read((int)$data['id']);
        }

        return $this->model->save($data);
    }

    /**
     * 批量新增/更新
     * @param array $data
     * @return Collection
     * @throws \Exception
     */
    public function saveAll(array $data): \think\model\Collection
    {
        return $this->model->saveAll($data);
    }

    public function update(array $data)
    {
        $query = $this->getQuery(__FUNCTION__, $data);

        return $query->update($data);
    }

    public function delete(array $data)
    {
        $query = $this->getQuery(__FUNCTION__, $data);

        return $query->delete();
    }

    /**
     * 从回收站读取一条数据
     *
     * @param int $id
     * @return CosyModel
     */
    public function readByRecycle(int $id): CosyModel
    {
        return $this
            ->model
            ->findOrEmpty($id);
    }
}